/*
 * Copyright (c) 2013-2015 Charkey. All rights reserved.
 *
 * This software is the confidential and proprietary information of Charkey.
 * You shall not disclose such Confidential Information and shall use it only
 * in accordance with the terms of the agreements you entered into with Charkey.
 *
 * Charkey MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
 *
 * Charkey SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
 * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 */

package cn.simastudio.talos.core.authc.filters;

import cn.simastudio.talos.common.constants.ApiStatusCode;
import cn.simastudio.talos.common.constants.SimaConstants;
import cn.simastudio.talos.common.model.JsonResult;
import cn.simastudio.talos.core.service.base.CoreToInterService;
import cn.simastudio.talos.core.service.base.OAuthService;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.web.servlet.OncePerRequestFilter;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * Usage: API访问权限过滤器：需要OAuth2认证后通过access_token和用于OAuth2认证的用户名
 *
 * @author Charkey
 * @date 2015/5/31 19:13
 */
@SuppressWarnings("SpringJavaAutowiringInspection")
public class ApiAccessRequestFilter extends OncePerRequestFilter {

    @Autowired
    private OAuthService oAuthService;

    @Autowired
    private CoreToInterService commonToInterService;

    @Override
    protected void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {

        // 获得 access_token：access_token 通过 header 传过来，格式为：Authorization: Bearer {用户授权得到的Bearer Token}
        String accessToken = ((HttpServletRequest) request).getHeader("Authorization");
        // 获得 Credential：授权的用户名
        String credential = ((HttpServletRequest) request).getHeader("Credential");

        // api 接口请求没有 access_token
        if (StringUtils.isEmpty(accessToken) || StringUtils.isEmpty(credential)) {
            StringBuilder errorDesc = new StringBuilder();
            if (StringUtils.isEmpty(accessToken)) {
                errorDesc.append("[Authorization]");
            }
            if (StringUtils.isEmpty(credential)) {
                errorDesc.append("[Credential]");
            }
            JsonResult result = new JsonResult();
            result.setCode(ApiStatusCode.BAD_REQUEST);
            result.setMessage("missing header: " + errorDesc.toString());
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(JSON.toJSONString(result));

        } else if (oAuthService.checkAccessTokenExpired(accessToken.replace("Bearer ", ""))) {
            JsonResult result = new JsonResult();
            result.setCode(ApiStatusCode.INVALID_ACCESS_TOKEN);
            result.setMessage("invalid access token");
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(JSON.toJSONString(result));

        } else if (!credential.substring(credential.indexOf(" ") + 1).equals(oAuthService.getCredentialByAccessToken(accessToken.replace("Bearer ", "")))) {
            JsonResult result = new JsonResult();
            result.setCode(ApiStatusCode.INVALID_CREDENTIAL);
            result.setMessage("invalid credential");
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(JSON.toJSONString(result));

        } else if (!commonToInterService.validCredential(credential)) {
            JsonResult result = new JsonResult();
            result.setCode(ApiStatusCode.INVALID_CREDENTIAL);
            result.setMessage("invalid credential");
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(JSON.toJSONString(result));

        } else {
            request.setAttribute(SimaConstants.System.API_CONSUMER, credential.substring(credential.indexOf(" ") + 1));
            request.setAttribute(SimaConstants.System.API_CONSUMER_ID, Integer.valueOf(credential.substring(0, credential.indexOf(" ") + 1).trim()));
            // 校验通过
            chain.doFilter(request, response);
        }
    }
}
